package com.eci.context.context.feign;


import com.eci.common.asset.core.R;
import com.eci.common.asset.enums.ScodeEnum;
import com.eci.common.util.JacksonUtil;
import com.eci.context.context.exception.BusinessException;
import okhttp3.*;
import okio.Buffer;
import okio.BufferedSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.EOFException;
import java.io.IOException;
import java.nio.charset.Charset;

@Component
public class LogOkInterceptor implements Interceptor {

    /**
     * 当前appName
     */
    @Value("${spring.application.name}")
    private String appName;

    public static final Charset UTF8 = Charset.forName("UTF-8");

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    public Response intercept(Chain chain) throws IOException {

        long startTime = System.currentTimeMillis();

        Request request = chain.request();

        //获取请求信息
        String requestStr = getRequestBodyStr(request);

        log.info("[{}]-->请求参数:{}", request.url(), requestStr);
        Response response = null;
        try {
            //执行请求
            response = chain.proceed(request);
        } catch (Exception e){
            log.error("feign调用异常", e);
            throw new BusinessException(appName + ScodeEnum.CALL_INNER_EXCEPTION.getCode(), ScodeEnum.CALL_INNER_EXCEPTION.getMessage());
        }

        //获取返回参数
        String resultStr = genResponseBodyStr(response);

        log.info("[{}]<--返回数据:{}|耗时:[{}ms]", request.url(), resultStr, System.currentTimeMillis() - startTime);

//        checkException(resultStr);

        return response;
    }

    public void checkException(String resultStr)
    {
        R baseRsp = JacksonUtil.readJson(resultStr, R.class);
        if (!ScodeEnum.SUCCESS.getCode().equals(baseRsp.getScode())) {
            //抛出我们的业务异常
            throw new BusinessException(baseRsp.getScode(), baseRsp.getMessage());
        }
    }

    private String genResponseBodyStr(Response response) throws IOException {
        ResponseBody responseBody = response.body();
        long contentLength = responseBody.contentLength();
        BufferedSource bufferedSource = responseBody.source();
        bufferedSource.request(Long.MAX_VALUE);
        Buffer buffer = bufferedSource.buffer();

        if (contentLength == 0) {
            log.info("无返回信息");
            return "";
        } else if (!isPlaintext(buffer)) {
            log.info("返回的数据格式不是字符串");
            return "";
        } else {
            return buffer.clone().readString(UTF8);
        }
    }

    private String getRequestBodyStr(Request request) throws IOException {
        RequestBody requestBody = request.body();

        if (requestBody != null) {
            Buffer buffer = new Buffer();
            requestBody.writeTo(buffer);
            return buffer.readString(UTF8);
        } else {
            return null;
        }
    }


    private boolean bodyEncoded(Headers headers) {
        String contentEncoding = headers.get("Content-Encoding");
        return contentEncoding != null && !contentEncoding.equalsIgnoreCase("identity");
    }


    static boolean isPlaintext(Buffer buffer) throws EOFException {
        try {
            Buffer prefix = new Buffer();
            long byteCount = buffer.size() < 64 ? buffer.size() : 64;
            buffer.copyTo(prefix, 0, byteCount);
            for (int i = 0; i < 16; i++) {
                if (prefix.exhausted()) {
                    break;
                }
                int codePoint = prefix.readUtf8CodePoint();
                if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) {
                    return false;
                }
            }
            return true;
        } catch (EOFException e) {
            return false;
        }
    }
}
